/*
 * $Id: pomodoro.c,v 1.53 2010/04/07 18:33:01 fabio Exp $
 */

#include <stdlib.h>
#include <string.h>
#include <cairo.h>
#include <gtk/gtk.h>
#include <glib.h>
#include <time.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "chrono.h"
#include "conf.h"
#include "twitter.h"
#include "pomodoro.xpm"

/* Clean up allocated memory and remove the timer */
static void destroy_progress(GtkWidget *widget, gpointer data) {
    ProgressData *pdata=(ProgressData *)data;
    char *msg="Shutting down";

    g_source_remove (pdata->timer);
    pdata->timer=0;
    pdata->window=NULL;
    g_free (pdata);
    g_print(msg);
    log_message("exiting: %s",msg);
    gtk_main_quit();
}

static gint eventDelete(GtkWidget *widget, GdkEvent *event, gpointer data) {
    ProgressData *pdata=(ProgressData *)data;

    gtk_widget_hide_all(pdata->window);
    pdata->visible=FALSE;

    return(TRUE);
}

static void append_list(gpointer data) {
    GtkWidget *list_item;
    ProgressData *pdata=(ProgressData *)data;
    time_t now=time(NULL);
    char *ct=ctime(&now);

    ct[strlen(ct)-1]='\0';
    pdata->last_message=malloc(256);
    bzero(pdata->last_message, 255);
    switch(pdata->status) {
        case RUNNING:
            sprintf(pdata->last_message, "%s Start Pomodoro '%s' %s %s",ct,print_time(pdata->pomodoro),print_time(pdata->tv),print_time(pdata->lap));
            break;
        case PAUSE:
            sprintf(pdata->last_message, "%s Pause Pomodoro '%s' %s %s",ct,print_time(pdata->pomodoro),print_time(pdata->tv),print_time(pdata->lap));
            break;
        case RESET:
            sprintf(pdata->last_message, "%s Reset Pomodoro '%s' %s %s",ct,print_time(pdata->pomodoro),print_time(pdata->tv),print_time(pdata->lap));
            break;
        case STOP:
            sprintf(pdata->last_message, "%s Completed Pomodoro '%s' %s %s",ct,print_time(pdata->pomodoro),print_time(pdata->tv),print_time(pdata->lap));
            break;
    }

    pdata->dlist=NULL;
    list_item=gtk_list_item_new_with_label(pdata->last_message);
    pdata->dlist=g_list_prepend(pdata->dlist, list_item);
    gtk_widget_show(list_item);
    gtk_list_insert_items(GTK_LIST(pdata->gtklist), pdata->dlist, 0);
    log_message("action: %s",pdata->last_message);
    if(pdata->twitter_integration) post_status(pdata);
}

static void startstop_app(gpointer data) {
    ProgressData *pdata=(ProgressData *)data;

    pdata->running=chrono(CHR_START_STOP, pdata);
    if(pdata->status==STOP||pdata->status==PAUSE||pdata->status==RESET) {
        pdata->status=RUNNING;
    } else {
        pdata->status=PAUSE;
    }
    append_list(data);
}

static void destroy_stop(GtkWidget *widget, gpointer data) {
    ProgressData *pdata=(ProgressData *)data;

    pdata->running=chrono(CHR_RESET, pdata);
}

static void stopnow(gpointer data) {
    GtkWidget *propert=NULL;
    GtkWidget *hbox, *wg, *panel;

    ProgressData *pdata=(ProgressData *)data;

    pdata->status=STOP;
    pdata->running=chrono(CHR_START_STOP, pdata);
    propert=gtk_window_new(GTK_WINDOW_TOPLEVEL);
    g_signal_connect (G_OBJECT (propert), "destroy", G_CALLBACK (destroy_stop), (gpointer) pdata);
    gtk_window_set_title(GTK_WINDOW (propert), "Stop now");

    gtk_window_set_position (GTK_WINDOW (propert), GTK_WIN_POS_MOUSE);
    gtk_window_set_modal (GTK_WINDOW (propert), TRUE);

    panel=gtk_vbox_new (FALSE, 0);
    gtk_container_border_width (GTK_CONTAINER (panel), 10);
    gtk_container_add (GTK_CONTAINER (propert), panel);
    gtk_widget_show (panel);

    hbox=gtk_hbox_new(FALSE, 00);
    gtk_container_add (GTK_CONTAINER(panel), hbox);
    gtk_widget_show(hbox);
    wg=gtk_label_new("Stop for while");
    gtk_box_pack_start(GTK_BOX(hbox), wg, FALSE, FALSE, 0);
    gtk_widget_show (wg);

    gtk_widget_show (propert);

    append_list(data);
}

static void reset_app(gpointer data) {
    ProgressData *pdata=(ProgressData *)data;

    if(pdata->status==RUNNING||pdata->status==PAUSE) {
        pdata->status=RESET;
        append_list(data);
        pdata->running=chrono(CHR_RESET, pdata);
    }
}

static gboolean time_handler(gpointer data) {
    char buffer[256];
    const gchar *text;
    int h, m, s, ms;
    gdouble new_val;
    struct timeval now;
    ProgressData *pdata=(ProgressData *)data;

    if (pdata->window->window == NULL) return FALSE;

    pdata->running=chrono(CHR_POLL, pdata);

    if(pdata->showcountdown) {
        now=pdata->pomodoro;
        if(now.tv_usec<0) now=(struct timeval){0,0};
    } else now=pdata->tv;
    ms=now.tv_usec/10000;
    h= now.tv_sec/3600;
    m=(now.tv_sec - h*3600)/60;
    s= now.tv_sec - h*3600 - m*60;
    bzero(buffer, 255);
    sprintf(buffer,"%02d:%02d:%02d.%02d", h, m, s, ms);

    text=gtk_progress_bar_get_text (GTK_PROGRESS_BAR (pdata->pbar));
    gtk_progress_bar_set_text (GTK_PROGRESS_BAR (pdata->pbar), buffer);
    if(pdata->status==RUNNING) {
        if (pdata->activity_mode) 
            gtk_progress_bar_pulse (GTK_PROGRESS_BAR (pdata->pbar));
        else  {
            /* Calculate the value of the progress bar using the
             * value range set in the adjustment object */

            new_val=gtk_progress_bar_get_fraction (GTK_PROGRESS_BAR (pdata->pbar)) + 0.01;

            if (new_val > 1.0)
                new_val=0.0;

            /* Set the new value */
            gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (pdata->pbar), new_val);
        }

        if(pdata->showcountdown && now.tv_usec==0) stopnow(data);
        else if(pdata->tv.tv_sec>=(pdata->previous_lap.tv_sec+pdata->p_secs)) stopnow(data);
    } else if(pdata->status==PAUSE) {
        gettimeofday(&now, NULL);
        if(now.tv_sec>=(pdata->interrupt.tv_sec+pdata->p_interrupt)) {
            startstop_app(pdata);
        }
    }

    return TRUE;
}

static void check_button_callback(GtkWidget *widget, gpointer data) {
    int *pdata=(int *)data;
    
    if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget))) {
        *pdata=1;
    } else  {
        *pdata=0;
    }
}

static void pwizard_text_change(GtkWidget *widget, char **text) {
    gchar *txt;

    txt=(gchar *)gtk_entry_get_text(GTK_ENTRY(widget));
    str_reset (text, txt);
}

static void xpdq_spin_value_changed(GtkWidget *widget, GtkSpinButton *spin) {
    long *num;

    num=gtk_object_get_user_data (GTK_OBJECT(spin));
    *num=gtk_spin_button_get_value_as_int (spin);
}

static void save_options_widget(gpointer data) {
    ProgressData *pdata=(ProgressData *)data;
    gchar *conffile=".pomodoro.conf";
    char buf[256],*h;
    FILE *f;

    if (!(h = getenv("HOME"))) {
        perror("getenv");
        exit(0);
    }
    snprintf(buf, sizeof(buf), "%s/%s", getenv("HOME"),conffile);
    if (!(f=fopen(buf, "w"))) {
        perror("write config");
        exit(0);
    }
    fprintf(f,"pomodoro_secs %d\n", pdata->p_secs);
    fprintf(f,"pomodoro_interrupt %d\n", pdata->p_interrupt);
    fprintf(f,"start_hidden %d\n", pdata->p_starthidden);
    fprintf(f,"show_countdown %d\n", pdata->showcountdown);
    fprintf(f,"activity_mode %d\n", pdata->activity_mode);
    fprintf(f,"twitter_integration %d\n", pdata->twitter_integration);
    fprintf(f,"twitter_username %s\n", pdata->twitter_username);
    fprintf(f,"twitter_password %s\n", pdata->twitter_password);
    if(pdata->proxy!=NULL&&strlen(pdata->proxy)>0) fprintf(f,"proxy %s\n", pdata->proxy);
    fclose(f);
    gtk_widget_destroy(pdata->config_win);
}

static void preferences(GtkWidget *widget, gpointer data) {
    GtkWidget *button, *hbox, *wg, *panel;
    GtkAdjustment *adj;
    ProgressData *pdata=(ProgressData *)data;

    pdata->config_win=gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title(GTK_WINDOW (pdata->config_win), "Preferences");
    gtk_container_set_border_width(GTK_CONTAINER(pdata->config_win), 5);
    gtk_window_set_resizable(GTK_WINDOW(pdata->config_win), TRUE);
    gtk_window_set_position (GTK_WINDOW (pdata->config_win), GTK_WIN_POS_MOUSE);
    gtk_window_set_modal (GTK_WINDOW (pdata->config_win), TRUE);

    panel=gtk_vbox_new (TRUE, 0);
    gtk_container_border_width (GTK_CONTAINER (panel), 10);
    gtk_container_add (GTK_CONTAINER (pdata->config_win), panel);
    gtk_widget_show (panel);

    hbox=gtk_hbox_new(FALSE, 00);
    gtk_container_add (GTK_CONTAINER(panel), hbox);
    gtk_widget_show(hbox);
    wg=gtk_label_new("Pomodoro setup to (seconds):");
    gtk_box_pack_start(GTK_BOX(hbox), wg, FALSE, FALSE, 0);
    gtk_widget_show (wg);
    adj=(GtkAdjustment *)gtk_adjustment_new (pdata->p_secs,0,1000000,1,3600,0);
    wg=gtk_spin_button_new (adj, 0.0, 0);
    gtk_signal_connect (GTK_OBJECT (adj), "value_changed",GTK_SIGNAL_FUNC (xpdq_spin_value_changed),(gpointer) wg);
    gtk_object_set_user_data (GTK_OBJECT(wg), &pdata->p_secs);
    gtk_box_pack_start(GTK_BOX(hbox), wg, TRUE, TRUE, 0);
    gtk_widget_show(wg);

    hbox=gtk_hbox_new(FALSE, 00);
    gtk_container_add (GTK_CONTAINER(panel), hbox);
    gtk_widget_show(hbox);
    wg=gtk_label_new("Pomodoro interrupt (seconds):");
    gtk_box_pack_start(GTK_BOX(hbox), wg, FALSE, FALSE, 0);
    gtk_widget_show (wg);
    adj=(GtkAdjustment *)gtk_adjustment_new (pdata->p_interrupt,0,1000000,1,3600,0);
    wg=gtk_spin_button_new (adj, 0.0, 0);
    gtk_signal_connect (GTK_OBJECT (adj), "value_changed",GTK_SIGNAL_FUNC (xpdq_spin_value_changed),(gpointer) wg);
    gtk_object_set_user_data (GTK_OBJECT(wg), &pdata->p_interrupt);
    gtk_box_pack_start(GTK_BOX(hbox), wg, TRUE, TRUE, 0);
    gtk_widget_show(wg);

    hbox=gtk_hbox_new(FALSE, 00);
    gtk_container_add (GTK_CONTAINER(panel), hbox);
    gtk_widget_show(hbox);
    wg=gtk_label_new("Start minimized:");
    gtk_box_pack_start(GTK_BOX(hbox), wg, FALSE, FALSE, 0);
    gtk_widget_show (wg);

    wg=gtk_check_button_new();    
    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(wg), pdata->p_starthidden);
    g_signal_connect (G_OBJECT(wg), "clicked", G_CALLBACK(check_button_callback), (gpointer)(&pdata->p_starthidden));
    gtk_box_pack_start(GTK_BOX(hbox), wg, FALSE, FALSE, 0);
    gtk_widget_show(wg);

    hbox=gtk_hbox_new(FALSE, 00);
    gtk_container_add (GTK_CONTAINER(panel), hbox);
    gtk_widget_show(hbox);
    wg=gtk_label_new("Show pomodoro countdown:");
    gtk_box_pack_start(GTK_BOX(hbox), wg, FALSE, FALSE, 0);
    gtk_widget_show (wg);

    wg=gtk_check_button_new();    
    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(wg), pdata->showcountdown);
    g_signal_connect (G_OBJECT(wg), "clicked", G_CALLBACK(check_button_callback), (gpointer)(&pdata->showcountdown));
    gtk_box_pack_start(GTK_BOX(hbox), wg, FALSE, FALSE, 0);
    gtk_widget_show(wg);

    hbox=gtk_hbox_new(FALSE, 00);
    gtk_container_add (GTK_CONTAINER(panel), hbox);
    gtk_widget_show(hbox);
    wg=gtk_label_new("Activity mode:");
    gtk_box_pack_start(GTK_BOX(hbox), wg, FALSE, FALSE, 0);
    gtk_widget_show (wg);

    wg=gtk_check_button_new();    
    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(wg), pdata->activity_mode);
    g_signal_connect (G_OBJECT(wg), "clicked", G_CALLBACK(check_button_callback), (gpointer)(&pdata->activity_mode));
    gtk_box_pack_start(GTK_BOX(hbox), wg, FALSE, FALSE, 0);
    gtk_widget_show(wg);

    hbox=gtk_hbox_new(FALSE, 00);
    gtk_container_add (GTK_CONTAINER(panel), hbox);
    gtk_widget_show(hbox);
    wg=gtk_label_new("Twitter integration:");
    gtk_box_pack_start(GTK_BOX(hbox), wg, FALSE, FALSE, 0);
    gtk_widget_show (wg);

    wg=gtk_check_button_new();    
    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(wg), pdata->twitter_integration);
    g_signal_connect (G_OBJECT(wg), "clicked", G_CALLBACK(check_button_callback), (gpointer)(&pdata->twitter_integration));
    gtk_box_pack_start(GTK_BOX(hbox), wg, FALSE, FALSE, 0);
    gtk_widget_show(wg);

    hbox=gtk_hbox_new(FALSE, 00);
    gtk_container_add (GTK_CONTAINER(panel), hbox);
    gtk_widget_show(hbox);
    wg=gtk_label_new("Twitter username:");
    gtk_box_pack_start(GTK_BOX(hbox), wg, FALSE, FALSE, 0);
    gtk_widget_show (wg);
    wg=gtk_entry_new();
    if(pdata->twitter_username!=NULL) gtk_entry_set_text(GTK_ENTRY(wg), pdata->twitter_username);
    gtk_signal_connect( GTK_OBJECT(wg), "changed",GTK_SIGNAL_FUNC(pwizard_text_change),(gpointer)(&pdata->twitter_username));
    gtk_box_pack_start(GTK_BOX(hbox), wg, TRUE, TRUE, 0);
    gtk_widget_show (wg);

    hbox=gtk_hbox_new(FALSE, 00);
    gtk_container_add (GTK_CONTAINER(panel), hbox);
    gtk_widget_show(hbox);
    wg=gtk_label_new("Twitter password:");
    gtk_box_pack_start(GTK_BOX(hbox), wg, FALSE, FALSE, 0);
    gtk_widget_show (wg);
    wg=gtk_entry_new();
    gtk_entry_set_visibility(GTK_ENTRY(wg), FALSE);
    if(pdata->twitter_password!=NULL) gtk_entry_set_text(GTK_ENTRY(wg), pdata->twitter_password);
    gtk_signal_connect( GTK_OBJECT(wg), "changed",GTK_SIGNAL_FUNC(pwizard_text_change),(gpointer)(&pdata->twitter_password));
    gtk_box_pack_start(GTK_BOX(hbox), wg, TRUE, TRUE, 0);
    gtk_widget_show (wg);

    hbox=gtk_hbox_new(FALSE, 00);
    gtk_container_add (GTK_CONTAINER(panel), hbox);
    gtk_widget_show(hbox);
    wg=gtk_label_new("Proxy:");
    gtk_box_pack_start(GTK_BOX(hbox), wg, FALSE, FALSE, 0);
    gtk_widget_show (wg);
    wg=gtk_entry_new();
    if(pdata->proxy!=NULL) gtk_entry_set_text(GTK_ENTRY(wg), pdata->proxy);
    gtk_signal_connect( GTK_OBJECT(wg), "changed",GTK_SIGNAL_FUNC(pwizard_text_change),(gpointer)(&pdata->proxy));
    gtk_box_pack_start(GTK_BOX(hbox), wg, TRUE, TRUE, 0);
    gtk_widget_show (wg);

    hbox=gtk_hbox_new(FALSE, 0);
    gtk_box_pack_end(GTK_BOX(panel), hbox, FALSE, FALSE, 0);
    gtk_widget_show(hbox);

    button=gtk_button_new_with_label ("Save");
    gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 10);
    gtk_signal_connect_object( GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(save_options_widget), pdata);
    gtk_widget_show(button);

    button=gtk_button_new_with_label ("Cancel");
    gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 5);
    gtk_signal_connect_object(GTK_OBJECT(button),"clicked",GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(pdata->config_win));
    gtk_widget_show(button);

    gtk_widget_show_all(pdata->config_win);
}

static gboolean key_event(GtkWidget *widget, GdkEventKey *event) {
    return TRUE;
}

static int viewLog(GtkWidget *widget, gpointer data) {
    GtkWidget *scrolledwindow,*textview;
    GtkTextBuffer *textbuffer;
    struct stat filestat;
    char *histfile=".pomodoro.history",*buffer,*h,buf[256];
    FILE *file;
    ProgressData *pdata=(ProgressData *)data;

    if (!(h = getenv("HOME")))
        return 0;
    snprintf(buf, sizeof(buf), "%s/%s",h,histfile);

    stat (buf, &filestat);
    buffer = (char *) malloc (filestat.st_size * sizeof (char));
    file = fopen (buf, "r");
    fread (buffer, filestat.st_size, 1, file);

    pdata->config_win = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    gtk_window_set_default_size (GTK_WINDOW (pdata->config_win), 500, 300);
    gtk_window_set_title(GTK_WINDOW (pdata->config_win), "History file");
    gtk_container_set_border_width(GTK_CONTAINER(pdata->config_win), 5);
    gtk_window_set_resizable(GTK_WINDOW(pdata->config_win), TRUE);
    gtk_window_set_position (GTK_WINDOW (pdata->config_win), GTK_WIN_POS_MOUSE);
    gtk_window_set_modal (GTK_WINDOW (pdata->config_win), TRUE);

    scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
    gtk_widget_show (scrolledwindow);
    gtk_container_add (GTK_CONTAINER (pdata->config_win), scrolledwindow);

    textview = gtk_text_view_new ();
    gtk_widget_show (textview);
    gtk_container_add (GTK_CONTAINER (scrolledwindow), textview);

    textbuffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (textview));
    gtk_text_buffer_set_text (textbuffer, buffer, filestat.st_size);
    free (buffer);

    g_signal_connect(G_OBJECT (pdata->config_win), "key-press-event", G_CALLBACK(key_event), NULL);
    g_signal_connect(G_OBJECT (pdata->config_win), "key-release-event", G_CALLBACK(key_event), NULL);
    g_signal_connect(G_OBJECT (pdata->config_win), "delete_event", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(pdata->config_win));

    gtk_widget_show (pdata->config_win);

    return 1;
}

static void tray_icon_on_click(GtkStatusIcon *status_icon, gpointer data) {
    ProgressData *pdata=(ProgressData *)data;

    if (pdata->visible) {
        gtk_widget_hide_all(pdata->window);
        pdata->visible=FALSE;
    } else {
        gtk_widget_show_all(pdata->window);
        pdata->visible=TRUE;
    }
}

static void tray_icon_on_menu(GtkStatusIcon *status_icon, guint button, guint activate_time, gpointer data) {
    GtkWidget *my_menu=NULL;
    ProgressData *pdata=(ProgressData *)data;

    if (!my_menu) {
        my_menu=gtk_menu_new();

        GtkMenuItem *menuitem_prop=GTK_MENU_ITEM(gtk_image_menu_item_new_from_stock(GTK_STOCK_PREFERENCES, NULL));
        gtk_menu_append(my_menu, GTK_WIDGET(menuitem_prop));
        g_signal_connect(G_OBJECT(menuitem_prop), "activate",G_CALLBACK(preferences), pdata);

        GtkWidget *menuitem_view=gtk_menu_item_new_with_label ("View history");
        gtk_menu_append(my_menu, GTK_WIDGET(menuitem_view));
        g_signal_connect(G_OBJECT(menuitem_view), "activate",G_CALLBACK(viewLog), pdata);

        GtkMenuItem *menuitem_quit=GTK_MENU_ITEM(gtk_image_menu_item_new_from_stock(GTK_STOCK_QUIT, NULL));
        gtk_menu_append(my_menu,GTK_WIDGET(menuitem_quit));
        g_signal_connect (G_OBJECT(menuitem_quit), "activate", G_CALLBACK(destroy_progress), pdata);
    }

    gtk_widget_show_all(my_menu);
    gtk_menu_popup(GTK_MENU(my_menu),NULL,NULL,gtk_status_icon_position_menu,status_icon,button,activate_time);
}

static GtkStatusIcon *create_tray_icon(gpointer data) {
    ProgressData *pdata=(ProgressData *)data;
    GtkStatusIcon *tray_icon;

    // Set up the status icon and connect the left-click and right-click signals
    tray_icon=gtk_status_icon_new_from_pixbuf(gdk_pixbuf_new_from_xpm_data((const char**) icon));
    g_signal_connect(G_OBJECT(tray_icon), "activate", G_CALLBACK(tray_icon_on_click), (gpointer)pdata);
    g_signal_connect(G_OBJECT(tray_icon), "popup-menu", G_CALLBACK(tray_icon_on_menu), (gpointer)pdata);
    gtk_status_icon_set_visible(tray_icon, TRUE);

    return tray_icon;
}

int main(int argc, char *argv[]) {
    GtkWidget *align,*separator,*table,*button,*vbox,*scrolled_window;
    GtkStatusIcon *tray_icon;
    ProgressData *pdata;

    /* Allocate memory for the data that is passed to the callbacks */
    pdata=g_malloc (sizeof (ProgressData));
    load_options(pdata);
    pdata->visible=TRUE;
    pdata->running=0;
    pdata->status=STOP;
    pdata->dlist=NULL;
    pdata->running=chrono(CHR_RESET, pdata);

    if(argc>1) {
        if(!strcmp(argv[1],"-c")) {
            chronometer(pdata);
            exit(0);
        } else {
            g_print("%s invalid parameter\n", argv[0]);
            exit(0);
        }
    }

    /* thread init */ 
    g_thread_init(NULL);
    gdk_threads_init();
    gtk_init (&argc, &argv);

    pdata->window=gtk_window_new (GTK_WINDOW_TOPLEVEL);
    gtk_window_set_resizable (GTK_WINDOW (pdata->window), TRUE);

    g_signal_connect(GTK_OBJECT(pdata->window), "delete_event", GTK_SIGNAL_FUNC(eventDelete), (gpointer)pdata);
    g_signal_connect(G_OBJECT (pdata->window), "destroy", GTK_SIGNAL_FUNC(destroy_progress), (gpointer)pdata);

    gtk_window_set_title (GTK_WINDOW (pdata->window), "Pomodoro");
    gtk_container_set_border_width (GTK_CONTAINER (pdata->window), 0);

    vbox=gtk_vbox_new (FALSE, 5);
    gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
    gtk_container_add (GTK_CONTAINER (pdata->window), vbox);
    gtk_widget_show (vbox);

    /* Create a centering alignment object */
    align=gtk_alignment_new (0.5, 0.5, 0, 0);
    gtk_box_pack_start (GTK_BOX (vbox), align, FALSE, FALSE, 5);
    gtk_widget_show (align);

    /* Create the GtkProgressBar */
    pdata->pbar=gtk_progress_bar_new ();

    gtk_container_add (GTK_CONTAINER (align), pdata->pbar);
    gtk_widget_show (pdata->pbar);

    /* Add a timer callback to update the value of the progress bar */
    pdata->timer=g_timeout_add (100, time_handler, pdata);

    /* This is the scrolled window to put the List widget inside */
    scrolled_window=gtk_scrolled_window_new(NULL, NULL);
    gtk_widget_set_usize(scrolled_window, 200, 100);
    gtk_container_add(GTK_CONTAINER(vbox), scrolled_window);
    gtk_widget_show(scrolled_window);

    /* Create thekList widget.
     * Connect the sigh_print_selection() signal handler
     * function to the "selection_changed" signal of the List
     * to print out the selected items each time the selection
     * has changed */
    pdata->gtklist=gtk_list_new();
    gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW(scrolled_window),
            pdata->gtklist);
    gtk_widget_show(pdata->gtklist);

    separator=gtk_hseparator_new ();
    gtk_box_pack_start (GTK_BOX (vbox), separator, FALSE, FALSE, 0);
    gtk_widget_show (separator);

    /* rows, columns, homogeneous */
    table=gtk_table_new (2, 3, FALSE);
    gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0);
    gtk_widget_show (table);

    /* Add a button to start */
    button=gtk_button_new_with_label ("start/pause");
    g_signal_connect_swapped (G_OBJECT (button), "clicked", G_CALLBACK(startstop_app), (gpointer)pdata);
    gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);

    /* Add a button to reset */
    button=gtk_button_new_with_label ("reset");
    g_signal_connect_swapped (G_OBJECT (button), "clicked", G_CALLBACK(reset_app), (gpointer)pdata);
    gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);

    /* This makes it so the button is the default. */
    GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);

    /* This grabs this button to be the default button. Simply hitting
     * the "Enter" key will cause this button to activate. */
    gtk_widget_grab_default (button);
    gtk_widget_show (button);

    g_timeout_add(150, (GSourceFunc) time_handler, pdata);
    gtk_widget_show_all(pdata->window);

    tray_icon=create_tray_icon(pdata);
    if(pdata->p_starthidden) {
        gtk_widget_hide_all(pdata->window);
        pdata->visible=FALSE;
    }

    gdk_threads_enter();
    gtk_main();
    gdk_threads_leave();

    return 0;
}
